Skip to content

fix(workflow): count a step's declared OUTPUT as delivery evidence - #2666

Merged
Birfy merged 1 commit into
mainfrom
fix/2658-step-artifacts-output
Nov 8, 2026
Merged

Birfy merged 1 commit into
mainfrom
fix/2658-step-artifacts-output

Conversation

@Birfy

@Birfy Birfy commented Nov 8, 2026 •

Copy link
Copy Markdown
Collaborator

Written-by: Dev

Fixes #2658

Owner: Dev
Reviewer: Reviewer

What changed

stepArtifacts() in plugins/workflow/src/graph.js now reads the step's own declared OUTPUT values as delivery evidence, beside the prose shapes it already accepted:

  • pr / pull: the first integer in the value (2657 (verified) → 2657); a value with no integer counts as nothing.
  • merged / merge-commit: a 40-character hexadecimal commit sha counts as delivered.
  • Any other output name, or a value of the wrong shape, counts for nothing. commitAdvance still requires the state verdict on every other path, and still fails a step that shows no delivery.

plugins/workflow/src/service.js lets that new merged evidence keep the state stand; missingVerdicts is unchanged. docs/subsystems/workflow.md records the widened evidence.

Red first

Before the implementation change, the new test file was 0/5 passing:

$ cd plugins/workflow && DSH_HARNESS=<installed 0.2.1-rc.2 harness> TZ=UTC node --import ./test/resolve.mjs --test test/step-artifacts.test.js

→ # tests 5 / # pass 0 / # fail 5; the i2656-shaped reply still settled commitAdvance at run.status = failed and stepArtifacts returned {pull:null,claimed:false}.

Ran at this tip: 0410da0

$ cd plugins/workflow && DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness TZ=UTC node --import ./test/resolve.mjs --test test/step-artifacts.test.js test/graph.test.js test/assign.test.js
$ cd plugins/workflow && DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness TZ=UTC node --import ./test/resolve.mjs --test "test/*.test.js"
$ node .github/scripts/changelog.mjs check
$ DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness node scripts/lint-plugins.mjs

→ 35 pass / 0 fail; 470 pass / 0 fail; 20 fragments well formed; 0 errors (warnings are pre-existing on main).

Not run

  • Full npm run verify: the brief allows one at a time and another inspection run holds it.
  • The core suite, build-client.mjs --check and ds-bot-patches check: no core/ file changed.
  • The tarball checkout has no node_modules; DSH_HARNESS pointed the tests at the installed 0.2.1-rc.2 harness.

Out of scope

  • The runner telling a node which OUTPUT its outgoing edges read.
  • partial settlement when a step is both failed and delivered.
  • Other stepArtifacts evidence shapes.

Checkpoint

{
"pr": 2666,
"claim": "Dev",
"issue": 2658,
"summary": "An issue fast-line step can now deliver its work as its own declared OUTPUT. stepArtifacts reads pr/pull for the first integer and merged/merge-commit for a 40-character sha, so a Triage reply like OUTPUT pr: 2657 (verified) no longer fails after its PR merged. Other names and shapes stay fail-closed, and every other missing verdict still fails.",
"files": [
"plugins/workflow/src/graph.js",
"plugins/workflow/src/service.js",
"plugins/workflow/test/step-artifacts.test.js",
"docs/subsystems/workflow.md",
"changelog.d/2658-step-artifacts-output.fixed.md"
],
"checks": {
"ran": "cd plugins/workflow && DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness TZ=UTC node --import ./test/resolve.mjs --test test/step-artifacts.test.js test/graph.test.js test/assign.test.js",
"result": "green",
"at": "0410da0d844df55cd781a3f145cfbfdc8dc77bae"
},
"next": "none — ready for review"
}

The issue fast line's Triage node prints `OUTPUT pr: 2657 (verified)` and never
names the pull request in prose, so stepArtifacts saw nothing, the #2583 stand
failed the step after the PR had already merged, and the run died as
`Missing OUTPUT state` with gate/enqueue/attest still queued.

stepArtifacts now reads the step's own declared OUTPUT too: `pr`/`pull` takes its
first integer, and `merged`/`merge-commit` counts with a 40-character sha. Other
names and shapes stay fail-closed, and every other path still requires the
`state` verdict. docs/subsystems/workflow.md records the widened evidence.

Fixes #2658
@Birfy Birfy added the agent-pr Pull request opened by an agent label Nov 8, 2026
@Birfy Birfy self-assigned this Nov 8, 2026
@Birfy

Birfy commented Nov 8, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at 0410da0
Written-by: Reviewer
Attestation: 0410da0 role=Reviewer

Ran at this tip:

$ cd plugins/workflow && TZ=UTC DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness node --import ./test/resolve.mjs --test test/step-artifacts.test.js test/graph.test.js test/assign.test.js
# tests 35  # pass 35  # fail 0
$ cp graph.base.js tip/plugins/workflow/src/graph.js   # base blob d02f292ff7d8 plugins/workflow/src/graph.js, new test kept
$ cd tip/plugins/workflow && TZ=UTC DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness node --import ./test/resolve.mjs --test test/step-artifacts.test.js
# tests 5  # pass 0  # fail 5
$ cp graph.tip.js tip/plugins/workflow/src/graph.js
$ cd tip/plugins/workflow && TZ=UTC DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness node --import ./test/resolve.mjs --test test/step-artifacts.test.js test/graph.test.js test/assign.test.js
# tests 35  # pass 35  # fail 0
$ cd tip/plugins/workflow && TZ=UTC DSH_HARNESS=/data/dsh/bot/workspace/d2607/repo/core/dev/harness node --import ./test/resolve.mjs --test test/missing-output-state.test.js
# tests 8  # pass 8  # fail 0
$ node --experimental-import-meta-resolve probe.mjs   # stepArtifacts shape probes
$ cd tip && node .github/scripts/changelog.mjs check
# 20 fragment(s) are well formed

Review notes (tip 0410da0d844d, base d02f292ff7d8, 5 files / 143+ / 3-):

Red first — hard requirement met. With plugins/workflow/src/graph.js swapped back to the base blob and the new test kept, test/step-artifacts.test.js is 0/5 passing (5 fail: the i2656 reply still settles commitAdvance as failed, and stepArtifacts returns {pull:null,claimed:false}). Restored to the tip it is 35/35 green across the three affected suites. No old test assertion was edited to get there: the diff touches only graph.js, service.js, the new test file, the subsystem doc and one changelog fragment.

Evidence shapes are tight (plugins/workflow/src/graph.js:116-146). Only PULL_OUTPUTS = {pr, pull} (first integer via /\d+/) and MERGE_OUTPUTS = {merged, merge-commit} (exactly /\b[0-9a-f]{40}\b/i) count; everything else is ignored. Probed directly: pr: "2657 (verified)" → 2657; pull: "12" → 12; pr: "none" → null; issue: "99" → null; merged: "not yet" / "f840979143b5" (39) / "deadbeef" → no merged; merged/merge-commit with a 40-hex sha → merged: true; tip: <sha> → null. There is no "any number in any OUTPUT is a PR" widening.

missingVerdicts is unchanged (fail-closed kept). service.js:1218 still computes missing the same way and stepArtifacts is only consulted when missing is exactly ['state']; every other missing gate-read output still becomes Missing OUTPUT <names>. test/missing-output-state.test.js (the #2583/#1773 fail-closed suite) is 8/8 green.

service.js change is one branch only. The single source edit is stands = artifact.pull != null || artifact.claimed || artifact.merged === true; run/node state-machine branches elsewhere are untouched. The new test drives the real fast line: i2656's reply (prose "已修复并合入" + PR #2657 with no creation verb, OUTPUT pr: 2657 (verified), OUTPUT merged: not yet) leaves run.status = running, triage = done, claim = running, escalate = skipped, producedPull = 2657; a merged: <sha>-only reply also keeps the run alive.

Scope. Only the declared evidence shapes and the one stands branch changed. The runner's edge-OUTPUT pre-announcement, partial settlement and other evidence shapes stay out, as the brief lists. docs/subsystems/workflow.md §5 records the widened evidence and changelog.d/2658-step-artifacts-output.fixed.md is a well-formed fragment.

CI at this tip. All check-runs green/skipped (tests-ok, Node 24 · DSH 0.2.0-rc.2, plugins (workflow/tree/social/timeline), package, policy-sign, merge-gate, reviewed tip, risk tier), the only red being enqueue-guard (no Verifier report names the tip 0410da0d), which this report clears.

Tier: T3 (plugins/workflow/**, not T0/T1) — this PASS at the tip is the review gate for it.

@github-actions github-actions Bot added the pass label Nov 8, 2026
@Birfy
Birfy added this pull request to the merge queue Nov 8, 2026
Merged via the queue into main with commit 3b8d4e8 Nov 8, 2026
20 checks passed
@Birfy
Birfy deleted the fix/2658-step-artifacts-output branch November 8, 2026 04:57
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Nov 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue line marks the run failed after its PR already merged: triage dies waiting on a background job

1 participant